History

Linux is an open-source OS
It's usually packaged into distributions that all use the same Kernel but add other open-source system software and libraries

Kernel was developed by Linus Torvalds

Linux System Architecture

System Calls

User programs need to access I/O devices, to interact with keyboard/mouse/disk/network, however the protection ring prevents direct access

OSs provide a collection of system calls

Library code is included of imported at the top of source code

Kernel Modules

The kernel is privileged (in every OS); it has no restrictions for any action
Device drivers also need privileged access to hardware
Linux has trusted device drivers built into the kernel itself

Monolithic Kernel Modular Kernel
Advantages - All drivers included when kernel is compiled - Specific drivers loaded when the system boots up
Disadvantages - Kernel image is very big on disk and in memory
- Need to recompile kernel to add new drivers or functionality
- Fragmentation of kernel memory as file systems and modules are loaded
- Security and stability risk from loading bad modules

Graphical and Terminal Shells

The original Unix/Linux shell was purely text based

Newer Linux distributions include various graphical shells

The Uni's Linux Farm

Sixteen servers called lxfarm01, lxfarm02, ... , lxfarm16
Connect via lxfarmXX.csc.liv.ac.uk
Each server has 8 physical CPUs (each with 4 cores)
Use MWS login details, may need to be on campus or using the VPN service

Directories

There are four special directory names

Paths can be absolute (from root) or relative (to where you are)

File Permissions

Permissions are shown as a 10 character string split into four parts:

Root User

The user root has full access to everything
Many system files and background processes are owned by the root user
Root user permissions can be requested by users using the sudo command

Setting Octal and Mnemonic Permissions

Use the chmod command to change the permissions of a file
To add write permission for the group: chmod g+w filename
To remove read permission for other: chmod o-r filename
You can also use octal numbers to change permissions quickly

(add up) User Group Other
Read 4 4 4
Write 2 2 2
Execute 1 1 1
Most files are set to 640 and most directories to 750

Assembly in Linux

Assembly code can be written and compiled in Linux with NASM

nasm -f elf32 hello.asm
ld -m elf_i386 hello.o -o hello
./hello

Code Example

Some code to display some text would look like:

global _start                     ; Tell linker where to start
section .data                     ; Constants go in .data section
	msg db 'Hello World!', 10, 0  ; db = define bytes (10 = \n)
	len dd 13                     ; dd = define dword (32 bits)

section .text                     ; Code goes in .text section
	_start:
		mov eax, 4                ; 4 = sys_write
		mov ebx, 1                ; 1 = file handle for STDOUT
		mov ecx, msg              ; Address of string
		mov edx, [len]            ; Length of string
		int 0x80                  ; Trigger interrupt
		mov eax, 1                ; 1 = sys_exit
		int 0x80                  ; 0x80 is 128 decimal

Process Creation

Processes are created (spawned) by other processes
The original process is the parent, the new process is the child
All running processes form a tree structure (which can be shown in Linux using the pstree command)
Everything has systemd as the top-level ancestor

There are several system calls in Linux that allow a process to spawn a child:

Fork

The fork() system call returns one of three possible values

int pid = fork();
// Call returns in each of the two processes
if(pid == 0) {
	printf("I'm the child process");
	// Will usually call exec() to load its own code
} else {
	printf("Im the parent and my child's ID is %d", pid);
}

The First Process

ROM stores a small program that runs a bootloader when a system is first turned on

Continues to run as a background process (daemon)

Shell Login

The sshd daemon runs in the background, waiting for incoming connections (spawned by systemd)

Processes are being created all the time

Running a Shell Command

When a command is type into the shell:

A desktop shell (GUI) does the same thing but with clicks to spawn processes

Zombies and Orphans

Parent processes usually wait for their children to die

The systemd process periodically cleans up zombies and orphans in the process table

Daemon Processes

Daemon processes such as sshd and systemd

Processes in the Linux File System

Kernel stores housekeeping information in the /proc directory

For example:

Subdirectory Purpose
/proc/PID/ Stores all the details and status of process PID
/proc/PID/cmdline The text that was typed to start the process
/proc/PID/fdinfo The status of any open files used by the process
/proc/PID/status The overall status of the process (lots of detail)
/proc/cpuinfo Stores details about the physical CPU(s)
/proc/modules Stores info about currently loaded kernel modules

There is a top command to see a dynamic (real-time) display of process details

Linux Signals

A process running from the terminal can usually be terminated by typing ^C (CTRL+C)

Responding to Signals

The process that receives a signal can respond in three ways

Code Number Meaning
SIGINT 2 Interrupted from keyboard (via CTRL+C)
SIGKILL 9 Request to terminate process (cannot be ignored)
SIGTERM 15 Request to terminate process (might be ignored)
SIGCHLD 17 Indicates that a child process has terminated
SIGIO 29 Indicates that input or output is ready

Terminating Zombie Processes

Imagine a parent process is badly coded:

The child will become a zombie

You can try to resend SIGCHLD to the parent but it will probably ignore it
So you'll have to send SIGKILL to the parent to kill it

Inter-Process Communication (IPC)

Processes need to communicate with each other

Shared memory and shared files allow two processes to access the same memory location or file at the same time

Pipes

A pipe is a form of IPC between two children of the same parent
Usually triggered by typing a command at the prompt

Sockets

A socket is a form of IPC that can span multiple systems

Client-Server Socket Handling

Server process uses the listen() system call to wait for clients

There is a diagram for this at the end of lecture 12